-
Notifications
You must be signed in to change notification settings - Fork 80
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Flight split based on condition #457
Conversation
Can we get this method into LazyTraffic? For example, the following code through error:
|
The proper way to add a method to traffic/src/traffic/core/traffic.py Line 736 in a83e95b
Note that the decorator will look for a method in Flight with the same name: traffic/src/traffic/core/lazy.py Line 341 in a83e95b
Lazy methodsAt the moment only two main categories of Flight methods are supported:
The most important category that is not supported as is are methods returning a Instead of
It could create a tree of executions, with possible RecursionError associated, and without the possibility to merge branches later:
A common use case with That pattern is supported in flight.aligned_on_ils("EHRD").next() # None | Flight
traffic.aligned_on_ils("EHRD").next().eval() # INVALID code
^__ returns a FlightIterator
^__ brings the FlightIterator back to a Flight You would write: traffic.next('aligned_on_ils("EHRD")').eval()
^__ next returns an Optional[Flight] On your examplet = (
t.iterate_lazy(iterate_kw=dict(by="6 hours"))
.assign_id(name="{self.callsign}_{idx:>04}") # you assign a flight_id
.filter()
.longer_than("1 hour")
.pipe(enough_data)
.split("30min", condition=no_split_enroute) # this returns a FlightIterator
.pipe(full_flight)
) The problem here that needs clarification is that when you split the trajectories, all the pieces will have the same flight_id. I am not sure if it is what you want. You may have wanted to put the That's the reason I am not very sure if I want to open the Pandora box with lazy flight iterators, because of this kind of situation. WorkaroundThere is however an example of a workaround in the following example, with the For your situation, I am not sure:
|
This is what I came up with in the end. Not pretty, but it work well. def no_split_enroute(f1: Flight, f2: Flight) -> bool:
return f1.data.iloc[-1].altitude < 25000 or f2.data.iloc[0].altitude < 25000
def resample_filter_split(flight: Flight) -> None | Flight:
flight_ = Traffic.from_flights(
[f.resample("2s").filter() for f in flight.split("10min")]
)[0] # 🌶️ I would recommend writing it Flight(pd.concat([...])) to avoid confusion with the [0] here
return flight_.split("30min", condition=no_split_enroute).all(
"{self.flight_id}_{i}"
) # 🌶️ This would be a perfect use case for flight_i.all('split("30min", condition=no_split_en_route)', flight_id="{self.flight_id}_{i}")
def full_flight(flight: Flight) -> None | Flight: # 🌶️ return a bool
if ( # 🌶️ replace 'if' with 'return'
flight.data.altitude.iloc[0] < 5000
and flight.data.altitude.iloc[-1] < 5000
and flight.altitude_max > 15000
):
return flight # 🌶️ remove
return None # 🌶️ remove
t = (
t.iterate_lazy(iterate_kw=dict(by="6 hours"))
.assign_id(name="{self.callsign}_{idx:>04}")
.filter()
.longer_than("1 hour")
.pipe(resample_filter_split)
.pipe(full_flight)
.eval(max_workers=8, desc="processing")
) |
Commenting directly in your code above |
You can now replace flight_ = Traffic.from_flights(
[f.resample("2s").filter() for f in flight.split("10min")]
)[0] with flight_ = flight.split('10min').map(lambda f: f.resample('2s').filter()).all() |
Yes, it works! I think it is good to be merged 👍 |
No description provided.